#include "MainFrame.h"
#include "TitleBar.h"
#include "TabBar.h"
#include "StatusBar.h"
#include "ContentWidget.h"
#include "../ModuleMgr.h"
#include "../CMD/CmdMgr.h"
#include "../CMD/Command.h"
#include <widgets/WidgetResizer.h>
#include <widgets/SBaseDialog.h>
#include <widgets/KeySearchWidget.h>
#include <widgets/SImageButton.h>
#include <core/Utility.h>
#include <core/FileSys.h>
#include <core/Events.h>
#include <core/StyleMgr.h>
#include <QBoxLayout>
#include <QApplication>
#include <QStylePainter>
#include <QMouseEvent>
#include <QStackedWidget>
#include <QTimer>
#include <QJsonObject>
#include <QJsonArray>
#include <QJsonValue>
#include <QPushButton>

MainFrame::MainFrame()
	: QWidget(nullptr)
{
	setWindowFlag(Qt::FramelessWindowHint);
	setFocusPolicy(Qt::StrongFocus);
	setMinimumSize(1020, 700);

	QVBoxLayout* mainLayout = new QVBoxLayout();
	mainLayout->setContentsMargins(1, 1, 1, 1);
	mainLayout->setSpacing(1);

	QVBoxLayout* topLayout = new QVBoxLayout();
	topLayout->setContentsMargins(0, 0, 0, 0);
	topLayout->setSpacing(0);

	m_title = new TitleBar(this);
	m_title->setFixedHeight(30);
	m_title->maximizeMainFrame(true);
	topLayout->addWidget(m_title);
	connect(this, &MainFrame::setCommonPage, m_title, &TitleBar::onCommonPage);

/*	m_relatedCmdBar = new QWidget(this);
	m_relatedCmdBar->setFixedHeight(26 * m_uiScale);
	QPalette palette = m_relatedCmdBar->palette();
	palette.setColor(QPalette::Window, QColor(0x080F0F));
	m_relatedCmdBar->setPalette(palette);
	m_relatedCmdBar->setAutoFillBackground(true);
	m_relatedCmdBar->hide();

	topLayout->addWidget(m_relatedCmdBar);*/
	mainLayout->addLayout(topLayout);
	
	m_contentWidget = new ContentWidget(this);
	m_contentWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
	mainLayout->addWidget(m_contentWidget);
	this->setLayout(mainLayout);

	m_resizer = new WidgetResizer(this);

//	connect(m_tabBar, &TabBar::tabClose, this, &MainFrame::onTabClose);
//	connect(m_tabBar, &TabBar::tabActivated, this, &MainFrame::onTabActivated);
//	connect(m_tabBar, &TabBar::tabSeperated, this, &MainFrame::onTabSeperated);

	qApp->installEventFilter(this);

	initializeCmdRelations();

//	QTimer::singleShot(0, this, &MainFrame::openHome);
}

void MainFrame::paintEvent(QPaintEvent* event)
{
	QStylePainter painter(this);
	painter.scale(m_uiScale, m_uiScale);
	painter.fillRect(rect(), NAME_COLOR("BasicBackground"));
}

bool MainFrame::eventFilter(QObject* watched, QEvent* event)
{
	if (event->type() == QEvent::KeyPress)
	{
		QWidget* foucsW = qApp->focusWidget();
		if (foucsW == nullptr || foucsW == this)
		{
			m_title->showSearch();
			m_title->searchWidget()->appendSearchText((static_cast<QKeyEvent*>(event))->text());
			m_title->searchWidget()->setFocus();
			return true;
		}
	}
	else if (event->type() == QEvent::Move) {
		//m_statusBar->OnWindowMoved();
	}
	return false;
}

int MainFrame::existCmdWindow(int cmdId, const QString& params, bool enableParam)
{
	int winId = -1;
	for(auto cmdWin : m_cmdWindows)
	{
		if(cmdWin.cmdId == cmdId && cmdWin.widget != nullptr && (!enableParam || cmdWin.params.compare(params, Qt::CaseInsensitive) == 0))
		{
			winId = cmdWin.winId;
			break;
		}
	}

	return winId;
}

int MainFrame::openCmdWindow(int cmdId, const QString& params, QWidget* widget, const QString& title, bool popup)
{
	int winId = -1;
	for(auto& cmdWin : m_cmdWindows)
	{
		if(cmdWin.cmdId == cmdId && cmdWin.params.compare(params, Qt::CaseInsensitive) == 0)
		{
			winId = cmdWin.winId;
			cmdWin.widget = widget;
			CmdWindowInfo* cwi = m_tabBar->tabById(winId);
			if (cwi)
				cwi->widget = widget;
			if (cmdWin.isPopup())
				cmdWin.widget->activateWindow();
			else
				m_tabBar->activateTabByTabId(cmdWin.winId);

			onTabActivated(winId);
			return winId;
		}
	}
	if (!popup)
	{
		//TODO: "fixed" as parameter
		CmdWindowInfo &ti = m_tabBar->addTab(title, widget, cmdId, cmdId == 20044);
		ti.params = params;
		m_cmdWindows[ti.winId] = ti;
		winId = ti.winId;
	}
	else
	{
		CmdWindowInfo ti;
		ti.cmdId = cmdId;
		ti.title = title;
		ti.winId = CmdMgr::instance().cmdWindowId();
		ti.setPopup(true);
		
		SBaseDialog* dlg = dynamic_cast<SBaseDialog*>(widget);
		if(dlg == nullptr)
		{
			dlg = new SBaseDialog(SBaseDialog::WindowType::kDialog);
			dlg->setContentWidget(widget);
			dlg->show();
		}
		ti.widget = widget;
		m_cmdWindows[ti.winId] = ti; 	
		winId = ti.winId;
	}
	
	onTabActivated(winId);

	return winId;
}

void MainFrame::activateCmdWindow(int tabId)
{
	if(m_tabBar->tabById(tabId))
		m_tabBar->activateTabByTabId(tabId);
	else
	{
		auto cw = m_cmdWindows.value(tabId);
		if(cw.widget)
			cw.widget->activateWindow();
	}
}

void MainFrame::updateWindowTitle(int windowId, const QString& title)
{
	if (m_tabBar->tabById(windowId))
	{
		m_tabBar->updateTabTitle(windowId, title);
	}
	else
	{
		auto cw = m_cmdWindows.value(windowId);
		if(cw.widget)
			cw.widget->setWindowTitle(title);
	}
}

//SLOTS:
void MainFrame::onTabClose(int tabId)
{
	CmdWindowInfo* ti = m_tabBar->tabById(tabId);
	if (!ti)
		return;

	closeWindow(tabId);
}

void MainFrame::onTabActivated(int newId)
{
}

void MainFrame::onTabSeperated(CmdWindowInfo ti)
{	
}

void MainFrame::onPopupMoving(SBaseDialog* dlg)
{
	QPoint mousePos = QCursor::pos();
	mousePos = m_tabBar->mapFromGlobal(mousePos);
	if (m_tabBar->rect().contains(mousePos))
	{
		for (auto& ti : m_cmdWindows)
		{
			if (dynamic_cast<SBaseDialog*>(ti.widget) == dlg)
			{
				dlg->setWindowType(SBaseDialog::WindowType::kChild);
			}
			else if (ti.widget == dlg->contentWidget())
			{
				dlg->removeContentWidget();
				dlg->deleteLater();
			}
			else
				continue;

			m_tabBar->attachWidget(ti);//will block until drag end!
			break;
		}
	}
}

void MainFrame::onPoupuClosed()
{
	SBaseDialog* sbd = dynamic_cast<SBaseDialog*>(sender());
	if (!sbd)
		return;
	QWidget* widget = dynamic_cast<QWidget*>(sbd);
	for (auto iter = m_cmdWindows.begin(); iter != m_cmdWindows.end(); ++iter)
	{
		if (iter->widget == widget || iter->widget == sbd->contentWidget())
		{
			closeWindow(iter.key());
			return;
		}
	}
}

void MainFrame::onRelationCmdClick()
{
	QString name = sender()->objectName();
	int cmdId = name.toInt();
	CmdMgr::instance().execCmd(cmdId);
}

void MainFrame::openHome()
{
	CmdMgr::instance().execCmd(20044);// 20044);
}

void MainFrame::initializeCmdRelations()
{
	QJsonDocument doc = CoreUtility::openJsonDoc(FileSys::instance()->appCfgDir() + "/menuRelation.json");
	if (doc.isEmpty())
		return;

	QJsonArray arr = doc.array();
	for (auto v : arr)
	{
		QJsonObject obj = v.toObject();
		QJsonArray ra = obj["relation"].toArray();
		QVector<int> relations;
		for (auto rv : ra)
		{
			relations.push_back(rv.toInt());
		}
		m_relationCmds.push_back(relations);
	}
}

void MainFrame::updateRelationBar(int activeCmd)
{
	//当已存在时，仅更新stylesheet
/*	if (m_curRelations.contains(activeCmd))
	{
		QString style = "QPushButton{background:#121A19; border-radius:0px;color:#FFE5C7}\nQPushButton:hover{background:#172422}\n"
			"#%1{background:#0C4F44}";
		style = style.arg(QString::number(activeCmd));
		m_relatedCmdBar->setStyleSheet(style);
		m_relatedCmdBar->show();
		return;
	}

	QHBoxLayout* l = dynamic_cast<QHBoxLayout*>(m_relatedCmdBar->layout());
	if (l)
	{
		QLayoutItem* child;
		while ((child = l->takeAt(0)) != nullptr) {
			delete child->widget(); // delete the widget
			delete child;   // delete the layout item
		}
	}
	else
	{
		l = new QHBoxLayout();
		l->setContentsMargins(0, 1 * m_uiScale, 0, 0);
		l->setSpacing(1 * m_uiScale);
		m_relatedCmdBar->setLayout(l);
	}

	m_curRelations.clear();
	for (auto rs : m_relationCmds)
	{
		for (auto r : rs)
		{
			if (r == activeCmd)
			{
				m_curRelations = rs;
				break;
			}
		}
	}
	
	if (m_curRelations.isEmpty())
	{
		m_relatedCmdBar->hide();
		return;
	}

	
	for (auto cmdId : m_curRelations)
	{
		Command* cmd = CmdMgr::instance().command(cmdId);
		if (!cmd)
			continue;
		QPushButton* btn = new QPushButton(cmd->name());
		btn->setObjectName(QString::number(cmdId));
		btn->setFixedSize(80 * m_uiScale, 25 * m_uiScale);
		l->addWidget(btn);

		connect(btn, &QPushButton::clicked, this, &MainFrame::onRelationCmdClick);
		connect(this, &MainFrame::scaleChanged, btn, [btn](float scale)
			{ btn->setFixedSize(80 * scale, 25 * scale); btn->resize(80 * scale, 25 * scale);
		QFont font = btn->font(); font.setPixelSize(12 * scale); btn->setFont(font); });
	}
	QPushButton* btn = new QPushButton();
	btn->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
	btn->setFixedHeight(25 * m_uiScale);
	connect(this, &MainFrame::scaleChanged, btn, [btn](float scale)
		{ btn->setFixedHeight( 25 * scale); btn->resize(1, 25 * scale); });
	btn->setDisabled(true);
	l->addWidget(btn);
	
	QString style = "QPushButton{background:#121A19; border-radius:0px;color:#FFE5C7}\nQPushButton:hover{background:#172422}\n"
					"#%1{background:#0C4F44}";
	style = style.arg(QString::number(activeCmd));
	m_relatedCmdBar->setStyleSheet(style);
	m_relatedCmdBar->show();*/
}

void MainFrame::closeWindow(int wid)
{
	if (!m_cmdWindows.contains(wid))
		return;

	CmdWindowInfo ti = m_cmdWindows[wid];
	m_cmdWindows.remove(wid);
	bool stillUsed = false;
	for (auto cmdWin : m_cmdWindows)
	{
		if (cmdWin.widget == ti.widget)
		{
			stillUsed = true; //but if we support dragout, this seems impossible!
			break;
		}
	}
}

void MainFrame::onScaleChanged(float scale)
{
	//Example!!! Please improve it!!!
	m_uiScale = scale;
	QFont font = QApplication::font();
	font.setPixelSize(12 * m_uiScale);//point size may more accurate,and shoud use the original font size!
	QApplication::setFont(font);

	//layout()->setContentsMargins(0 * m_uiScale, 0 * m_uiScale, 0 * m_uiScale, 0 * m_uiScale);
	//layout()->setSpacing(1 * m_uiScale);

/*	m_relatedCmdBar->setFixedHeight(26 * m_uiScale);
	m_relatedCmdBar->resize(m_relatedCmdBar->width() * m_uiScale, 26 * m_uiScale);

	if (m_relatedCmdBar->layout())
	{
		m_relatedCmdBar->layout()->setContentsMargins(0, 1 * m_uiScale, 0, 0);
		m_relatedCmdBar->layout()->setSpacing(1 * m_uiScale);
	}*/

	scaleChanged(m_uiScale);
	updateGeometry();

	QWidgetList wl = QApplication::allWidgets();
	for (QWidget* w : wl)
	{
		QApplication::postEvent(w, new QEvent((QEvent::Type)SSEventType::UserScaleChanged));
	}
}

void MainFrame::setNetworkStatus(int status) {
	//Q_ASSERT_X(m_statusBar, "setNetworkStatus", "m_statusBar is nullptr");
	//m_statusBar->setNetworkStatus(status);
}

void MainFrame::setMsgCenterNotify(int count) {
	//Q_ASSERT_X(m_statusBar, "setMsgCenterNotify", "m_statusBar is nullptr");
	//m_statusBar->setMsgCenterNotify(count);
}

void MainFrame::setCommonPageNotify(int* ids, int size, int ntype)
{
	setCommonPage(ids, size, ntype);
}

void MainFrame::setIasMenuNotify(const QString& iasmenu)
{
	CmdMgr::instance().setIasMenu(iasmenu);
}

KeySearchWidget* MainFrame::searchWidget()
{
	return m_title->searchWidget();
}

QWidget* MainFrame::cmdWindow(int tabid)
{
	CmdWindowInfo* cwi = m_tabBar->tabById(tabid);
	if (cwi)
		return cwi->widget;
	
	return nullptr;
}